package com.xy.tool.data.redis.util;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Date;
import java.util.Objects;

import static com.xy.tool.data.redis.util.TimeUtils.getExpiredSecondsVariation;

public class RedisUtils {

    public static <V> void expire(RedisTemplate<String, V> redisTemplate, Collection<String> keys, long seconds) {
        Objects.requireNonNull(redisTemplate, "The redisTemplate is required.");
        if(CollectionUtils.isEmpty(keys)) {
            return;
        }
        if(seconds < 1) {
            return;
        }
        redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Nullable
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                for (String key : keys) {
                    connection.expire(RedisSerializer.string().serialize(key),
                            seconds + getExpiredSecondsVariation(seconds));
                }
                return null;
            }
        });
    }

    public static <V> void expireAt(RedisTemplate<String, V> redisTemplate, Collection<String> keys, Date date) {
        Objects.requireNonNull(redisTemplate, "The redisTemplate is required.");
        if(CollectionUtils.isEmpty(keys)) {
            return;
        }
        if(null == date || date.getTime() <= System.currentTimeMillis()) {
            return;
        }
        redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Nullable
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                try {
                    for(String key : keys) {
                        connection.pExpireAt(RedisSerializer.string().serialize(key), date.getTime());
                    }
                } catch (Exception e) {
                    for (String key : keys) {
                        connection.expireAt(RedisSerializer.string().serialize(key), date.getTime() / 1000L);
                    }
                }
                return null;
            }
        });
    }

}
